﻿using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using iWare.Wms.Core;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Linq.Dynamic.Core;
using Yitter.IdGenerator;

namespace iWare.Wms.Application
{
    /// <summary>
    /// 送货预约服务
    /// </summary>
    [Route("api/GoodsDeliveryAppointment")]
    [ApiDescriptionSettings("供应商模块", Name = "GoodsDeliveryAppointment", Order = 100)]

    public class GoodsDeliveryAppointmentService : IDynamicApiController, ITransient
    {
        private readonly IRepository<PurchaseOrder, MasterDbContextLocator> _purchaseOrderRep;
        private readonly IRepository<GoodsDelivery, MasterDbContextLocator> _goodsDeliveryRep;
        private readonly IRepository<GoodsDeliveryDetails, MasterDbContextLocator> _goodsDeliveryDetailsRep;
        private readonly IRepository<GoodsDeliveryAppointment, MasterDbContextLocator> _goodsDeliveryAppointmentRep;
        private readonly IRepository<SupplierExamineFlower, MasterDbContextLocator> _supplierExamineFlowerRep;
        private readonly IRepository<WareDictData, MasterDbContextLocator> _wareDictDataRep;

        #region 默认
        /// <summary>
        /// 默认
        /// </summary>
        /// <param name="purchaseOrderRep"></param>
        /// <param name="goodsDeliveryRep"></param>
        /// <param name="goodsDeliveryDetailsRep"></param>
        /// <param name="goodsDeliveryAppointmentRep"></param>
        /// <param name="supplierExamineFlowerRep"></param>
        /// <param name="wareDictDataRep"></param>
        public GoodsDeliveryAppointmentService(
            IRepository<PurchaseOrder, MasterDbContextLocator> purchaseOrderRep,
            IRepository<GoodsDelivery, MasterDbContextLocator> goodsDeliveryRep,
            IRepository<GoodsDeliveryDetails, MasterDbContextLocator> goodsDeliveryDetailsRep,
            IRepository<GoodsDeliveryAppointment, MasterDbContextLocator> goodsDeliveryAppointmentRep,
            IRepository<SupplierExamineFlower, MasterDbContextLocator> supplierExamineFlowerRep,
            IRepository<WareDictData, MasterDbContextLocator> wareDictDataRep
        )
        {
            _purchaseOrderRep = purchaseOrderRep;
            _goodsDeliveryRep = goodsDeliveryRep;
            _goodsDeliveryDetailsRep = goodsDeliveryDetailsRep;
            _goodsDeliveryAppointmentRep = goodsDeliveryAppointmentRep;
            _supplierExamineFlowerRep = supplierExamineFlowerRep;
            _wareDictDataRep = wareDictDataRep;
        }
        #endregion

        /// <summary>
        /// 分页查询供应商送货预约
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("Page")]
        public async Task<PageResult<GoodsDeliveryOutput>> Page([FromQuery] GoodsDeliveryAppointmentSearch input)
        {
            var userId = CurrentUserInfo.UserId;

            var goodsDelivery = await _goodsDeliveryRep.DetachedEntities
                .Where(p => p.CreatedUserId == userId)
                .Where(input.Status != AuditStatusEnum.all, p => p.Status == input.Status)
                .Where(input.IsJiaJiJian != null && input.IsJiaJiJian != YesOrNot.All, u => u.IsJiaJiJian == input.IsJiaJiJian)
                .Where(!string.IsNullOrEmpty(input.DeliveryNo), u => EF.Functions.Like(u.DeliveryNo, $"%{input.DeliveryNo.Trim()}%"))
                .Where(!string.IsNullOrEmpty(input.ProjectCode), u => EF.Functions.Like(u.ProjectCode, $"%{input.ProjectCode.Trim()}%"))
                .Where(!string.IsNullOrEmpty(input.PurchaseNo), u => EF.Functions.Like(u.PurchaseNo, $"%{input.PurchaseNo.Trim()}%"))
                .Where(!string.IsNullOrEmpty(input.DeliveryType), u => EF.Functions.Like(u.DeliveryType, $"%{input.DeliveryType.Trim()}%"))
                .Where(!string.IsNullOrEmpty(input.SearchBeginTime), u => u.CreatedTime >= DateTime.Parse(input.SearchBeginTime.Trim()) &&
                 u.CreatedTime <= DateTime.Parse(input.SearchEndTime.Trim()))
                .OrderByDescending(z => z.DeliveryType == "UrgentItem")
                .ThenBy(z => z.Status)
                .ThenByDescending(z => z.CreatedTime)
                .ProjectToType<GoodsDeliveryOutput>()
                .ToADPagedListAsync(input.PageNo, input.PageSize);

            foreach (var item in goodsDelivery.Rows)
            {
                if (item.GoodsDeliveryAppointments != null)
                {
                    if (!string.IsNullOrEmpty(item.GoodsDeliveryAppointments.Images) && item.GoodsDeliveryAppointments.Images != "N/A")
                    {
                        var imageList = item.GoodsDeliveryAppointments.Images.Split(',');

                        if (imageList.Count() > 1)
                        {
                            var list = new List<long>();
                            foreach (var image in imageList)
                            {
                                list.Add(Convert.ToInt64(image));
                            }
                            item.GoodsDeliveryAppointments.ImagesList = list;
                        }
                        else
                        {
                            var list = new List<long>();
                            list.Add(Convert.ToInt64(item.GoodsDeliveryAppointments.Images));
                            item.GoodsDeliveryAppointments.ImagesList = list;
                        }
                    }
                    else if (item.GoodsDeliveryAppointments.Images != "N/A")
                    {
                        var list = new List<long>();
                        list.Add(Convert.ToInt64(item.GoodsDeliveryAppointments.Images));
                        item.GoodsDeliveryAppointments.ImagesList = list;
                    }
                    else
                    {
                        item.GoodsDeliveryAppointments.ImagesList = null;
                    }
                }

                item.GoodsDeliveryId = item.GoodsDeliveryDetails != null && item.GoodsDeliveryDetails.Count > 0 ? item.GoodsDeliveryDetails.FirstOrDefault().GoodsDeliveryId : 0;
                item.PurchaseNo = (await _purchaseOrderRep
                    .Where(t => t.PurchaseNo.Equals(item.PurchaseNo) && t.PurchaseType.Equals(item.DeliveryType))
                    .FirstOrDefaultAsync()).IsJiaJiJian == YesOrNot.Y ? "" : item.PurchaseNo;
                item.PurchaseTypeName = (await _wareDictDataRep.FirstOrDefaultAsync(z => z.Code == item.DeliveryType)).Value;
            }

            return goodsDelivery;
        }

        /// <summary>
        /// 分页查询供应商送货单明细
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("DetailPage")]
        public async Task<PageResult<GoodsDeliveryDetailsOutput>> DetailPage([FromQuery] GoodsDeliveryDetailsSearch input)
        {
            var goodsDeliveryDetailss = await _goodsDeliveryDetailsRep.DetachedEntities
                .Where(input.GoodsDeliveryId != null, u => u.GoodsDeliveryId == input.GoodsDeliveryId)
                .Where(!string.IsNullOrEmpty(input.Code), u => u.Code == input.Code)
                .Where(!string.IsNullOrEmpty(input.Name), u => u.Name == input.Name)
                .OrderBy(t => t.XuHao)
                .ProjectToType<GoodsDeliveryDetailsOutput>()
                .ToADPagedListAsync(input.PageNo, input.PageSize);

            var goodsDelivery = await _goodsDeliveryRep.FirstOrDefaultAsync(n => n.Id == input.GoodsDeliveryId);

            foreach (var item in goodsDeliveryDetailss.Rows)
            {
                item.DeliveryNo = goodsDelivery.DeliveryNo;
                item.ProjectCode = goodsDelivery.ProjectCode;
                item.CreatedTime = goodsDelivery.CreatedTime;
                item.BrandName = string.IsNullOrEmpty(item.BrandName) || item.BrandName == "无" ? "" : item.BrandName;
            }

            return goodsDeliveryDetailss;
        }

        /// <summary>
        /// 根据送货单ID查询送货预约并且编辑
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("GetAddEdit")]
        public async Task<GoodsDeliveryAppointmentOutput> GetAddEdit([FromQuery] QueryeGoodsDeliveryAppointmentInput input)
        {
            var GoodsDeliveryAppointmentModel = await _goodsDeliveryAppointmentRep.DetachedEntities
                .Where(p => p.DeliveryID == input.DeliveryID)
                .ProjectToType<GoodsDeliveryAppointmentOutput>().FirstOrDefaultAsync();

            var supplierExamineFlowerDto = await _supplierExamineFlowerRep
                .Where(GoodsDeliveryAppointmentModel != null, p => p.DeliveryID == GoodsDeliveryAppointmentModel.DeliveryID)
                .OrderBy(p => p.CreatedTime)
                .ProjectToType<SupplierExamineFlowerDto>().ToListAsync();

            if (GoodsDeliveryAppointmentModel != null)
                GoodsDeliveryAppointmentModel.SupplierExamineFlowerDto = supplierExamineFlowerDto;

            return GoodsDeliveryAppointmentModel;
        }

        /// <summary>
        /// 新增送货预约
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("Add")]
        //[UnitOfWork]
        public async Task Add(AddGoodsDeliveryAppointmentInput input)
        {
            var appointmenModel = await _goodsDeliveryAppointmentRep.DetachedEntities.SingleOrDefaultAsync(u => u.DeliveryID == input.DeliveryId);

            var deliveryModel = await _goodsDeliveryRep.DetachedEntities.SingleOrDefaultAsync(u => u.Id == input.DeliveryId);
            if (deliveryModel.Status != AuditStatusEnum.yuyuezhong && deliveryModel.Status != AuditStatusEnum.yuyuechenggong && deliveryModel.Status != AuditStatusEnum.bohui)
                throw Oops.Oh("审核和送货中的单据不能进行预约信息编辑");
            if (input.DeliverDate > input.EstimatedDate) throw Oops.Oh("预计到达日期不能少于发货日期");

            //进行修改
            if (appointmenModel != null)
            {
                input.Id = appointmenModel.Id;
                appointmenModel = input.Adapt<GoodsDeliveryAppointment>();
                appointmenModel.Images = input.Images != null && input.Images.Count > 0 ? string.Join(",", input.Images) : "N/A";
                await _goodsDeliveryAppointmentRep.UpdateAsync(appointmenModel, true);
            }
            else
            {
                //新增送货预约
                appointmenModel = input.Adapt<GoodsDeliveryAppointment>();
                appointmenModel.TransportCompany = !string.IsNullOrEmpty(input.TransportCompany) ? input.TransportCompany : "N/A";
                appointmenModel.TransportVehicle = !string.IsNullOrEmpty(input.TransportVehicle) ? input.TransportVehicle : "N/A";
                appointmenModel.DriverName = !string.IsNullOrEmpty(input.DriverName) ? input.DriverName : "N/A";
                appointmenModel.DriverPhone = !string.IsNullOrEmpty(input.DriverPhone) ? input.DriverPhone : "N/A";
                appointmenModel.DriverQualification = !string.IsNullOrEmpty(input.DriverQualification) ? input.DriverQualification : "N/A";
                appointmenModel.ExpressInfoNo = !string.IsNullOrEmpty(input.ExpressInfoNo) ? input.ExpressInfoNo : "N/A";
                appointmenModel.CollectDeliveryUserName = !string.IsNullOrEmpty(input.CollectDeliveryUserName) ? input.CollectDeliveryUserName : "N/A";
                appointmenModel.CollectDeliveryUserPhone = !string.IsNullOrEmpty(input.CollectDeliveryUserPhone) ? input.CollectDeliveryUserPhone : "N/A";
                appointmenModel.DeliverGoodsPlaceShip = !string.IsNullOrEmpty(input.DeliverGoodsPlaceShip) ? input.DeliverGoodsPlaceShip : "N/A";
                appointmenModel.DeliveryID = deliveryModel.Id;
                appointmenModel.DeliveryNo = deliveryModel.DeliveryNo;
                appointmenModel.PurchaseNo = deliveryModel.PurchaseNo;
                appointmenModel.Images = input.Images != null && input.Images.Count > 0 ? string.Join(",", input.Images) : "N/A";
                await _goodsDeliveryAppointmentRep.InsertAsync(appointmenModel);

                //更新送货单状态
                deliveryModel.Status = AuditStatusEnum.yuyuechenggong; //预约成功
                await _goodsDeliveryRep.UpdateAsync(deliveryModel, false);

                //创建一条提交记录
                var supplierExaminerFlowerModel = new SupplierExamineFlower()
                {
                    Status = AuditStatusEnum.yuyuechenggong, //预约成功
                    DeliveryID = deliveryModel.Id,
                    Remarks = "预约成功"
                };
                await _supplierExamineFlowerRep.InsertAsync(supplierExaminerFlowerModel);
            }
        }

        /// <summary>
        /// 删除送货预约
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("Delete")]
        public async Task Delete(DeleteGoodsDeliveryAppointmentInput input)
        {
            var isExist = await _goodsDeliveryAppointmentRep.AnyAsync(u => u.Id == input.Id[0], false);
            if (!isExist) throw Oops.Oh("数据不存在");

            var goodsDeliveryAppointment = await _goodsDeliveryAppointmentRep.FirstOrDefaultAsync(u => u.Id == input.Id[0]);
            await _goodsDeliveryAppointmentRep.DeleteAsync(goodsDeliveryAppointment);
        }

        /// <summary>
        /// 更新送货预约
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("Edit")]
        public async Task Edit(UpdateGoodsDeliveryAppointmentInput input)
        {
            var isExist = await _goodsDeliveryAppointmentRep.AnyAsync(u => u.Id == input.Id, false);
            if (!isExist) throw Oops.Oh("数据不存在");

            var goodsDeliveryAppointment = input.Adapt<GoodsDeliveryAppointment>();
            await goodsDeliveryAppointment.UpdateAsync(ignoreNullValues: true);
        }

        /// <summary>
        /// 提交送货预约信息
        /// </summary>
        /// <returns></returns>
        [HttpPost("Submit")]
        //[UnitOfWork]
        public async Task Submit(SubmitGoodsDeliveryAppointmentInput input)
        {
            //判断预约信息是否存在
            var IsResult = await _goodsDeliveryAppointmentRep.AnyAsync(p => p.DeliveryID == input.DeliveryID);
            if (!IsResult) throw Oops.Oh("未提交预约信息");

            //更新送单号的信息的状态
            var deliveryModel = await _goodsDeliveryRep.SingleAsync(u => u.DeliveryNo == input.DeliveryNo, true);
            deliveryModel.Status = AuditStatusEnum.shenhezhong;  //审核中
            await _goodsDeliveryRep.UpdateAsync(deliveryModel);

            //创建一条提交记录
            var supplierExaminerFlowerModel = new SupplierExamineFlower()
            {
                Status = AuditStatusEnum.shenhezhong, //审核中
                DeliveryID = deliveryModel.Id,
                Remarks = "审核中"
            };
            await _supplierExamineFlowerRep.InsertAsync(supplierExaminerFlowerModel);
        }

        /// <summary>
        /// 打印送货单
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("Print")]
        public async Task<GoodsDeliveryOutput> Print([FromQuery] PrintGoodsDeliveryInput input)
        {
            var model = await _goodsDeliveryRep.DetachedEntities.Where(u => u.Id == input.DeliveryID).ProjectToType<GoodsDeliveryOutput>().FirstOrDefaultAsync();
            if (model != null)
            {
                var purchaseOrder = await _purchaseOrderRep.FirstOrDefaultAsync(z => z.PurchaseNo == model.PurchaseNo && z.SupplierInfoCode == model.SuppCode);
                var wareDictData = await _wareDictDataRep.FirstOrDefaultAsync(z => z.Code == purchaseOrder.PurchaserUserId);

                model.PurchaseNo = purchaseOrder.IsJiaJiJian == YesOrNot.Y ? "" : purchaseOrder.PurchaseNo;
                model.ReceUser = wareDictData == null ? "" : wareDictData.Value;

                // 根据序号排序
                var deliveryDetailsList = model.GoodsDeliveryDetails.OrderBy(t => t.XuHao);

                var xuHao = 0; //定义序号
                foreach (var item in deliveryDetailsList)
                {
                    item.DeliveryNo = model.DeliveryNo;
                    item.BrandName = string.IsNullOrEmpty(item.BrandName) || item.BrandName == "无" ? "" : item.BrandName;

                    // 如果是加急件，序号赋值
                    if (item.GoodsDelivery.IsJiaJiJian == YesOrNot.Y)
                    {
                        xuHao = xuHao + 1;
                        item.XuHao = xuHao.ToString("0000");
                    }
                }
                return model;
            }
            else return null;
        }

        /// <summary>
        /// 查询供应商送货预约信息
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetAppointment")]
        public async Task<AppointmentDetailsOutput> GetAppointment()
        {
            var userId = CurrentUserInfo.UserId;
            var model = new AppointmentDetailsOutput();
            var gdaList = await _goodsDeliveryAppointmentRep.DetachedEntities.Where(p => p.CreatedUserId == userId).ToListAsync();

            model.TransportCompanyList = gdaList.Where(p => p.TransportCompany != "" && p.TransportCompany != "N/A")
                .Select(t => t.TransportCompany).Distinct().ToList();
            model.TransportVehicleList = gdaList.Where(p => p.TransportVehicle != "" && p.TransportVehicle != "N/A")
                .Select(t => t.TransportVehicle).Distinct().ToList();
            model.DriverNameList = gdaList.Where(p => p.DriverName != "" && p.DriverName != "N/A")
                .Select(t => t.DriverName).Distinct().ToList();
            model.DriverPhoneList = gdaList.Where(p => p.DriverPhone != "" && p.DriverPhone != "N/A")
                .Select(t => t.DriverPhone).Distinct().ToList();
            model.DriverQualificationList = gdaList.Where(p => p.DriverQualification != "" && p.DriverQualification != "N/A")
                .Select(t => t.DriverQualification).Distinct().ToList();
            model.ExpressInfoNoList = gdaList.Where(p => p.ExpressInfoNo != "" && p.ExpressInfoNo != "N/A")
                .Select(t => t.ExpressInfoNo).Distinct().ToList();
            model.CollectDeliveryUserNameList = gdaList.Where(p => p.CollectDeliveryUserName != "" && p.CollectDeliveryUserName != "N/A")
                .Select(t => t.CollectDeliveryUserName).Distinct().ToList();
            model.CollectDeliveryUserPhoneList = gdaList.Where(p => p.CollectDeliveryUserPhone != "" && p.CollectDeliveryUserPhone != "N/A")
                .Select(t => t.CollectDeliveryUserPhone).Distinct().ToList();
            model.DeliverGoodsPlaceShipList = gdaList.Where(p => p.DeliverGoodsPlaceShip != "" && p.DeliverGoodsPlaceShip != "N/A")
                .Select(t => t.DeliverGoodsPlaceShip).Distinct().ToList();

            // 收货地址
            var collectDeliveryPlaceShip = new List<string>();
            var placeShipDistinct = gdaList.Where(p => p.CollectDeliveryPlaceShip != "" && p.CollectDeliveryPlaceShip != "N/A")
                .Select(t => t.CollectDeliveryPlaceShip).Distinct().ToList();

            foreach (var item in placeShipDistinct)
            {
                collectDeliveryPlaceShip.Add(item);
            }
            collectDeliveryPlaceShip.Add("上海市松江区文吉路555号");
            collectDeliveryPlaceShip.Add("上海市松江区东兴路398号");

            model.CollectDeliveryPlaceShip = collectDeliveryPlaceShip.Distinct().ToList();
            return model;
        }

        /// <summary>
        /// 查询供应商全部审核记录
        /// </summary>
        /// <returns></returns>
        [HttpGet("ExamineFlowerByAppointment")]
        public async Task<List<SupplierExamineFlowerByAppointmentOutput>> ExamineFlowerByAppointment([FromQuery] SupplierExamineFlowerByAppointmentInput input)
        {
            return await _supplierExamineFlowerRep.DetachedEntities
                 .Where(z => z.DeliveryID == input.DeliveryID).ProjectToType<SupplierExamineFlowerByAppointmentOutput>()
                 .OrderByDescending(z => z.CreatedTime).ToListAsync();
        }

        /// <summary>
        /// 生成系统单号
        /// </summary>
        /// <returns></returns>
        [HttpGet("GenerateSystemNo")]
        public string GenerateSystemNo()
        {
            return YitIdHelper.NextId().ToString();
        }
    }
}
